package com.hanxiaozhang.exception;


import com.hanxiaozhang.result.Result;
import com.hanxiaozhang.result.ResultCode;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

/**
 * 功能描述: <br>
 * 〈处理Zuul出现的异常〉
 * 两种方式 :
 * 1.自定义error错误页面（如下）
 * 2.禁用zuul默认的异常处理filter（SendErrorFilter），自定义ErrorFilter
 * https://blog.csdn.net/qq_31349087/article/details/79614184
 *
 * @Author:hanxiaozhang
 * @Date: 2020/7/20
 */
@Slf4j
@RestController
public class ErrorHandlerController implements ErrorController {

    @RequestMapping(value = "/error")
    public ResponseEntity<Result> error(HttpServletRequest request) {
        log.info("into ErrorHandlerController.error");
        RequestContext ctx = RequestContext.getCurrentContext();
        if (ctx.isEmpty() || ctx.getThrowable() == null) {
            Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
            HashMap<String, Object> map = new HashMap<String, Object>(2) {{
                put("status", statusCode);
            }};
            return new ResponseEntity<>(Result.error(ResultCode.ZUUL_EXCEPTION, map), HttpStatus.valueOf(statusCode));
        }
        ZuulException exception = findZuulException(ctx.getThrowable());
        return new ResponseEntity<>(Result.error(ResultCode.ZUUL_EXCEPTION, exception, HttpStatus.BAD_GATEWAY), HttpStatus.BAD_GATEWAY);

    }

    @Override
    public String getErrorPath() {
        return "/error";
    }


    ZuulException findZuulException(Throwable throwable) {

        // 这是由一个本地筛选器引发的故障
        if (throwable.getCause() instanceof ZuulRuntimeException) {
            return (ZuulException) throwable.getCause().getCause();
        }

        if (throwable.getCause() instanceof ZuulException) {
            return (ZuulException) throwable.getCause();
        }

        // zuul生命周期引发的异常
        if (throwable instanceof ZuulException) {
            return (ZuulException) throwable;
        }

        // fallback
        return new ZuulException(throwable, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
    }


}